#!/bin/bash
# vim:ts=4:sw=4:noexpandtab
#
# Copyright (c) 2004-2014 Parallels IP Holdings GmbH.
# All rights reserved.
# http://www.parallels.com


export PATH=/bin:/sbin:/usr/bin:/usr/sbin

self="$0"
cmd=$1

shift

SCRIPT_NAME=$(basename "$self")
RT_ROOT=

make_rt_dirs() {
	local tmp_dir='/tmp/.pd'
	RT_ROOT="${tmp_dir}/`id -u`"
	mkdir -p "${RT_ROOT}"/{tmp,var/{run,log,tmp}} || echo "mkdir -p failed"
	chmod a+rwxt "${tmp_dir}" 2>/dev/null
}

init_runtime() {
	local uid=$(id -u)
	[ ${uid} -ne 0 ] && make_rt_dirs
}

function pid_file_name() {
	local executable="$1"
	local pid_hash=$(echo "$executable" | md5 | sed -E 's/^.{20}//')
	echo "${RT_ROOT}/var/run/prl_watchdog-${pid_hash}.pid"
}

# Log to syslog and stderr
# usage: log <error|warning|debug> "MESSAGE"
function log {
	local level=$1
	shift
	case "${level}" in
		error)   logger -t "${SCRIPT_NAME}" -p error -s "$@"
			 ;;
		warning)   logger -t "${SCRIPT_NAME}" -p warning -s "$@"
			 ;;
		info)   logger -t "${SCRIPT_NAME}" -p info -s "$@"
			 ;;
		debug)   [ "$_DEBUG" == "true" ] && logger -t "${SCRIPT_NAME}" -p debug s "$@"
			 ;;
		*)	 logger -t "${SCRIPT_NAME}" -s "${level} $@"
			 ;;
	esac
}


function start_watch() {
	local timeout="$1"
	local restarts_limit="$2"
	local executable="$3"

	shift; shift; shift

	watchdog_pid="$(cat "$(pid_file_name "$executable")" 2>/dev/null)"
	if [[ ! -z $watchdog_pid ]] && kill -0 $watchdog_pid > /dev/null ; then
		echo "watchdog for $executable is already running, pid -${watchdog_pid}-"
		return
	fi

	if [[ -z $restarts_limit || "$restarts_limit" < "0" ]]; then
		restarts_limit=0
	fi

	log "Start watching $executable (limit is $restarts_limit)"
	echo -n "$$" > "$(pid_file_name "$executable")"

	local child_pid=""
	local restarts_count=0
	while true
	do
		if [ -z $child_pid ] || ! kill -0 $child_pid > /dev/null ; then
			if [[ -z $child_pid ]]; then
				log "Start $executable $@"
			else
				restarts_count=$(($restarts_count + 1))
				log "Restarting $executable $@ ($restarts_count of $restarts_limit)"
			fi

			"$executable" "$@" &
			child_pid="$!"
			log "Child pid $child_pid"
			if [[ "$restarts_limit" != "0" && $restarts_limit -lt $restarts_count ]]; then
				log "Restart limit is reached, close watchdog..."
				exit 0
			fi
		else
			restarts_count=0
		fi
		sleep $timeout
	done
}

function stop_watch() {
	local cmd=$1
	local executable=$2
	shift 2

	log "Stop watching $executable"
	local pid_file="$(pid_file_name "$executable")"
	local watchdog_pid="$(cat "$pid_file" 2>/dev/null)"
	log "file $pid_file, pid $watchdog_pid"

	if [[ ! -z $watchdog_pid ]]; then
		kill -SIGTERM "$watchdog_pid"
		rm -f "$pid_file"
	else
		log "No self watchdog found"
	fi
	
	case "$cmd" in
		'stop')
			log "$executable $@"
			"$executable" "$@"
			;;
		'kill')
			local pid=$1
			log "sending SIGTERM to $executable ($pid)"
			kill -SIGTERM "$pid"
			;;
		*)
			log error "Incorrect stop command '$cmd'"
			return 1
			;;
	esac
}


init_runtime

case $cmd in
	"start") start_watch "$@" ;;
	"stop") stop_watch stop "$@" ;;
	"kill") stop_watch kill "$@" ;;
	*) log "Usage: $0 <start <>timeout>|stop> <cmd [args]>" ;;
esac

